package com.example.wx.dailyreport.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.wx.dailyreport.mapper.RoleMapper;
import com.example.wx.dailyreport.mapper.UserRoleMapper;
import com.example.wx.dailyreport.pojo.Role;
import com.example.wx.dailyreport.pojo.RoleAuthorities;
import com.example.wx.dailyreport.pojo.RoleAuthority;
import com.example.wx.dailyreport.pojo.UserRole;
import com.example.wx.dailyreport.service.RoleAuthorityService;
import com.example.wx.dailyreport.service.RoleService;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.LinkedList;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author hulinbo
 * @since 2020-07-30
 */
@Service
@Transactional
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {

    private static final int SIZE = 100;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private RoleAuthorityService roleAuthorityService;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Override
    public List<RoleAuthorities> selectRoleInPage(Role role, Long authority_flag, int page, int limit) {
        int skip = (page - 1) * limit;
        return roleMapper.selectRoleBy(role, authority_flag, skip, limit);
    }

    @Override
    public int selectRoleCount(Role role, Long authority_flag) {
        return roleMapper.selectRoleCountBy(role, authority_flag);
    }

    @Override
    public boolean updateRole(Role role, Integer[] authorityids) {
        int update = roleMapper.updateById(role);

        UpdateWrapper<RoleAuthority> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(RoleAuthority::getRoleId, role.getId());
        roleAuthorityService.remove(updateWrapper);

        if (ArrayUtils.isNotEmpty(authorityids)) {
            List<RoleAuthority> roleAuthorityList = new LinkedList<>();
            for (Integer aid : authorityids) {
                RoleAuthority roleAuthority = new RoleAuthority();
                roleAuthority.setRoleId(role.getId());
                roleAuthority.setAuthorityId(aid);
                roleAuthorityList.add(roleAuthority);
            }
            roleAuthorityService.saveBatch(roleAuthorityList);
        }
        return update > 0;
    }

    @Override
    public boolean insertRole(Role role, Integer[] authorityids) {
        role.setFlag((long) Math.pow(2, roleMapper.selectCount(new QueryWrapper<>())));
        int insert = roleMapper.insert(role);
        if (ArrayUtils.isNotEmpty(authorityids)) {
            List<RoleAuthority> roleAuthorityList = new LinkedList<>();
            for (Integer aid : authorityids) {
                RoleAuthority roleAuthority = new RoleAuthority();
                roleAuthority.setRoleId(role.getId());
                roleAuthority.setAuthorityId(aid);
                roleAuthorityList.add(roleAuthority);
            }
            roleAuthorityService.saveBatch(roleAuthorityList);
        }
        return insert > 0;
    }

    @Override
    public boolean deleteRole(Integer id) {
        long flag = roleMapper.selectById(id).getFlag();
        int delete = roleMapper.deleteById(id);

        UpdateWrapper<UserRole> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(UserRole::getRoleId, id);
        userRoleMapper.delete(updateWrapper);

        QueryWrapper<Role> roleQueryWrapper = new QueryWrapper<>();
        roleQueryWrapper.lambda().gt(Role::getFlag, flag);

        Integer count = roleMapper.selectCount(roleQueryWrapper);
        int page = (int) Math.ceil(count / (double) SIZE);
        if (page > 0) {
            for (int i = 0; i < page; i++) {
                IPage<Role> iPage = new Page<>(i * SIZE, SIZE);
                IPage<Role> roleIPage = roleMapper.selectPage(iPage, roleQueryWrapper);
                LinkedList<Role> pageRecords = new LinkedList<>(roleIPage.getRecords());
                int len = pageRecords.size();
                for (int j = 0; j < len; j++) {
                    Role role = pageRecords.removeFirst();
                    role.setFlag(flag * (long) Math.pow(2, j));
                    pageRecords.addLast(role);
                }
                updateBatchById(pageRecords);
            }
        }
        return delete > 0;
    }
}